package com.ruijie.autotest.log.validation.paiboftp.wifitrack;

import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.ruijie.autotest.log.core.validate.IValidator;
import com.ruijie.autotest.log.impl.validate.SolidValueValidator;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;
import java.util.regex.Pattern;

import static com.ruijie.autotest.log.impl.validate.SqlExistingValidator.sqlExistingVerificationOf;
import static com.ruijie.autotest.log.impl.validate.SqlMappedExistingValidator.mappedVerification;

@SpringBootConfiguration
public class Config {
	@Bean
	public DataSource dataSource() {
		return new ComboPooledDataSource("remote");
	}

	@Bean
	public IValidator versionValidator() {
		return new SolidValueValidator("1.0.0");
	}

	@Bean
	public IValidator eventTypeValidator(DataSource dataSource) {
		return mappedVerification("eg_auth_log.end_time", this::toEventType, dataSource);
	}

	@Bean
	public IValidator docVersionValidator() {
		return new SolidValueValidator("4.3.3");
	}

	@Bean
	public IValidator authTypeValidator(DataSource dataSource) {
		return mappedVerification("eg_auth_log.auth_account", this::toAuthType, dataSource);
	}

	@Bean
	public IValidator authAccountValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.auth_account", dataSource);
	}

	@Bean
	public IValidator idTypeValidator(DataSource dataSource) {
		return mappedVerification("eg_auth_log.auth_account", this::toIDType, dataSource);
	}

	@Bean
	public IValidator idCodeValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.auth_account", dataSource);
	}

	@Bean
	public IValidator idNameValidator() {
		return new SolidValueValidator("");
	}

	@Bean
	public IValidator appCompanyValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.app_company_name", dataSource);
	}

	@Bean
	public IValidator appNameValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.app_software_name", dataSource);
	}

	@Bean
	public IValidator appVersionValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.app_version", dataSource);
	}

	@Bean
	public IValidator appAuthcodeValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.appid", dataSource);
	}

	@Bean
	public IValidator locationCodeValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("s_location.code", dataSource);
	}

	@Bean
	public IValidator locationTypeValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("s_location_type.code", dataSource)
				.or(""::equals);
	}

	@Bean
	public IValidator loginAtValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.start_time", dataSource);
	}

	@Bean
	public IValidator logoutAtValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.start_time", dataSource);
	}

	@Bean
	public IValidator macValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.mac", dataSource);
	}

	@Bean
	public IValidator lanIpValidator(DataSource dataSource) {
		return mappedVerification("eg_auth_log.ip_address",
				item -> toWanIP(Long.valueOf(item)),
				dataSource);
	}

	@Bean
	public IValidator sourceIp4Validator(DataSource dataSource) {
		return mappedVerification("eg_auth_log.src_ip",
				item -> longToIP(Long.valueOf(item)),
				dataSource);
	}

	@Bean
	public IValidator sourceIp6Validator(DataSource dataSource) {
		return mappedVerification("eg_auth_log.src_ipv6",
				item -> longToIP(Long.valueOf(item)),
				dataSource);
	}

	@Bean
	public IValidator sourceStartport4Validator(DataSource dataSource) {
		// FIXME 2021/1/12  wait for me!!!     may cause error
		return mappedVerification("eg_auth_log.src_port_start",
				item -> String.valueOf(toSrcPortStart(Integer.valueOf(item))),
				dataSource);
	}

	@Bean
	public IValidator sourceEndport4Validator(DataSource dataSource) {
		return mappedVerification("eg_auth_log.src_port_end",
				item -> String.valueOf(toSrcPortEnd(Integer.valueOf(item))),
				dataSource);
	}

	@Bean
	public IValidator sourceStartport6Validator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.src_port_start_v6", dataSource);
	}

	@Bean
	public IValidator sourceEndport6Validator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.src_port_end_v6", dataSource);
	}

	@Bean
	public IValidator apidValidator(DataSource dataSource) {
		return mappedVerification("eg_auth_log.collection_equipment_id",
				this::toCollectioneEquipmentId,
				dataSource);
	}

	@Bean
	public IValidator apmacValidator(DataSource dataSource) {
		return mappedVerification("eg_auth_log.ap_mac",
				this::toAPMac,
				dataSource);
	}

	@Bean
	public IValidator longitudeValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("s_device.longitude", dataSource);
	}

	@Bean
	public IValidator latitudeValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("s_device.latitude", dataSource);
	}

	@Bean
	public IValidator rssiValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.terminal_field_strength", dataSource);
	}

	@Bean
	public IValidator sessionidValidator(DataSource dataSource) {
		return mappedVerification("eg_auth_log.session_id",
				this::toSessionID,
				dataSource);
	}

	@Bean
	public IValidator xValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.x_coordinate", dataSource);
	}

	@Bean
	public IValidator yValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.y_coordinate", dataSource);
	}

	@Bean
	public IValidator imsiValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.imsi", dataSource);
	}

	@Bean
	public IValidator deviceIdValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.imei_esn_meid", dataSource);
	}

	@Bean
	public IValidator terminalSystemValidator(DataSource dataSource) {
		return new SolidValueValidator("99");
	}

	@Bean
	public IValidator terminalBrandValidator(DataSource dataSource) {
		return new SolidValueValidator("99");
	}

	@Bean
	public IValidator terminalBrandtypeValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.model", dataSource);
	}

	@Bean
	public IValidator sourceValidator(DataSource dataSource) {
		return new SolidValueValidator("17");
	}

	@Bean
	public IValidator ispIdValidator(DataSource dataSource) {
		return new SolidValueValidator("");
	}

	@Bean
	public IValidator wanIpValidator(DataSource dataSource) {
		return mappedVerification("eg_auth_log.src_ip",
				item -> toWanIP(Long.valueOf(item)),
				dataSource);
	}

	@Bean
	public IValidator ssidValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.ssid", dataSource);
	}

	@Bean
	public IValidator associatedValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("eg_auth_log.ssid", dataSource);
	}

	@Bean
	public IValidator floorValidator(DataSource dataSource) {
		return sqlExistingVerificationOf("s_device.floor", dataSource);
	}

	@Bean
	public IValidator loginTypeValidator(DataSource dataSource) {
		return new SolidValueValidator("30");
	}

	@Bean
	public IValidator plastersignValidator(DataSource dataSource) {
		return new SolidValueValidator("0");
	}

	@Bean
	public IValidator metroStationInfoValidator(DataSource dataSource) {
		return new SolidValueValidator("");
	}

	private String toEventType(String endTime) {
		String result;
		if ("0000-00-00 00:00:00".equals(endTime)) { //上线
			result = "40";
		} else { //下线
			result = "41";
		}
		return result;
	}

	public static boolean isNumEx(String str) {
		if ((str == null) || (str.length() <= 0)) {
			return false;
		}

		char[] ch = str.toCharArray();

		int i = 0;
		for (int comcount = 0; i < str.length(); i++) {
			if (!Character.isDigit(ch[i])) {
				if (ch[i] != '.') {
					return false;
				}
				if ((i == 0) || (i == str.length() - 1)) {
					return false;
				}
				comcount++;
				if (comcount > 1) {
					return false;
				}
			}
		}
		return true;
	}

	private String toAuthType(String authAccount) {
		if (isNumEx(authAccount) && authAccount.length() == 11) {
			return "1020004";
		} else if (isWellFormattedMacAddress(authAccount)) {
			return "1020002";
		} else {
			return "1029999";
		}
	}

	public static boolean isWellFormattedMacAddress(String mac) {
		if (Pattern
				.compile("[0-9a-fA-F]{2}[:-][0-9a-fA-F]{2}[:-][0-9a-fA-F]{2}[:-][0-9a-fA-F]{2}[:-][0-9a-fA-F]{2}[:-][0-9a-fA-F]{2}").matcher(mac).matches())
			return true;

		if (Pattern.compile("[0-9a-fA-F]{4}[.-][0-9a-fA-F]{4}[.-][0-9a-fA-F]{4}").matcher(mac).matches())
			return true;

		if (Pattern.compile("[0-9a-fA-F]{12}").matcher(mac).matches())
			return true;

		return false;
	}

	private String toIDType(String authAccount) {
		if (isNumEx(authAccount) && authAccount.length() == 11) {
			return "19";
		} else if (isWellFormattedMacAddress(authAccount)) {
			return "81";
		} else {
			return "15";
		}
	}

	private int toSrcPortStart(Integer srcPortStart) {
		int result = srcPortStart;
		if (result == 0) {
			result = 2060;
		}
		return result;
	}

	private int toSrcPortEnd(Integer srcPortEnd) {
		int result = srcPortEnd;
		if (result == 65535) {
			result = 2060;
		}
		return result;
	}

	private String toAPMac(String apMac) {
		return convertMacWithBarUpperCase(apMac);
	}

	public static String convertMacWithBarUpperCase(String mac) {
		String newMac = convertMacWithBar(mac);
		if (newMac != null) {
			return newMac.toUpperCase();
		} else {
			return null;
		}
	}

	public static String convertMacWithBar(String mac) {
		if (null == mac)
			return null;
		String tmp = CharMatcher.JAVA_LETTER_OR_DIGIT.retainFrom(mac);
		return Joiner.on("-").join(Splitter.fixedLength(2).split(tmp));
	}

	private String toCollectioneEquipmentId(String collectioneEquipmentId) {
		return collectioneEquipmentId.toUpperCase();
	}

	private String toSessionID(String sessionId) {
		return sessionId.toUpperCase();
	}

	private String toWanIP(Long srcIp) {
		if (srcIp == null) {
			return "";
		}
		long y = srcIp % 256;
		long m = (srcIp - y) / (256 * 256 * 256);
		long n = (srcIp - 256 * 256 * 256 * m - y) / (256 * 256);
		long x = (srcIp - 256 * 256 * 256 * m - 256 * 256 * n - y) / 256;
		return m + "." + n + "." + x + "." + y;
	}

	private static String longToIP(Long ipaddr) {
		if (ipaddr == null) {
			return "";
		}
		long y = ipaddr % 256;
		long m = (ipaddr - y) / (256 * 256 * 256);
		long n = (ipaddr - 256 * 256 * 256 * m - y) / (256 * 256);
		long x = (ipaddr - 256 * 256 * 256 * m - 256 * 256 * n - y) / 256;
		return m + "." + n + "." + x + "." + y;
	}
}
